[アップデート] AWS Elemental MediaPackageでCDN認証が利用可能になりエンドポイントが保護できるようになりました!
はじめに
清水です。AWS Media Servicesの2020年1つ目のアップデート情報はこちら!動画配信におけるジャストインタイムパッケージングサービスであるAWS Elemental MediaPackageでCDN認証が利用可能になり、エンドポイントを保護できるようになりました。(2020/01/02にポストされたアップデートになります。)
- Secure AWS Elemental MediaPackage Live Endpoints Using CDN Authorization
- CDN 認証を使用して AWS Elemental MediaPackage ライブエンドポイントを保護する
動画配信を行う際にはMediaPackageなどをオリジンとして、実際のアクセスはAmazon CloudFrontなどCDNを利用することが多いかと思います。この際MediaPackageのエンドポイントに対してはCDN以外からのアクセスができないよう、オリジン保護をしておきたいですね。今回アップデートされたMediaPackageのCDN認証(オリジン保護)機能では、コンテンツをリクエストする際に特定のHTTPオリジンヘッダと認証コードが必要となります。イメージとしては以下のような、CloudFront+ALB構成でオリジンを保護する方法と同様になるかと思います。
- CloudFront専用のALBをリクエストルーティングで設定してみた | Developers.IO
- AWS WAFを利用してCloudFrontのELBオリジンへ直接アクセスを制限してみた | Developers.IO
なお、現在のところCDN認証機能はMediaPackageのライブパッケージングのみで利用可能とのことです。VODパッケージングでは現段階ではサポートされていないので注意しましょう。
AWS Elemental MediaPackageでCDN認証を行いオリジン保護してみた
それでは実際にMediaPackageでCDN認証機能を使ってみます。User Guideの以下ページを参考に進めました。(2020/01/03現在、日本語版ページがまだなかったため、英語版ページを参照しています。)
IAMロールの準備
MediaPackageでCDN認証機能を使用する場合、MediaPackageからAWS Secrets Managerへのアクセスが必要となります。このアクセスを許可するIAMロールを準備します。必要なアクセス許可については、こちらもUser Guideを参考に決定しました。(こちらも2020/01/03現在、日本語版ページがなかったため英語版ページを参照しています。)
IAMポリシーの作成
マネジメントコンソールのIAM > Access managementのPoliciesから、[Create policy]でポリシーを作成します。ポリシーの内容は以下のJSONとします。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "secretsmanager:GetSecretValue", "secretsmanager:DescribeSecret", "secretsmanager:ListSecrets", "secretsmanager:ListSecretVersionIds" ], "Resource": [ "*" ] }, { "Effect": "Allow", "Action": [ "iam:GetRole", "iam:PassRole" ], "Resource": "*" } ] }
IAMポリシー名はMediaPackageCDNAuthPolicyとしました。
IAMロールの作成
続いて作成したIAMポリシーをアタッチするIAMポリシーを作成します。マネジメントコンソールのIAM > Access managementのRolesから[Create role]で進みます。ロールを使用するサービスの選択箇所ではMediaPackageがないので、ひとまずEC2を選択して次に進みましょう。
アタッチするポリシー選択画面では、先程作成したIAMポリシー、MediaPackageCDNAuthPolicyを選択します。
IAMロール名はMediaPackageCDNAuthRoleとしました。
IAMロールの信頼関係の編集
続いて作成したIAMロールの信頼関係を編集します。ロール作成時には使用するサービス選択箇所でMediaPackageがなかったため、EC2を選択していました。この箇所を編集して、MediaPackageから使用可能にします。マネジメントコンソールのIAM > Access managementのRolesから、作成したIAMロール(MediaPackageCDNAuthRole)の詳細画面に進みます。[Trust rrelationships]のタブから、[Edit trust relationship]ボタンで編集画面に進みます。
JSON中の"Service": "ec2.amazonaws.com"の箇所を"Service": "mediapackage.amazonaws.com"と変更します。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" // ここを "mediapackage.amazonaws.com" に変更 }, "Action": "sts:AssumeRole" } ] }
編集後は[Trust relationships]タブのTrusted entitiesの箇所がThe identity provider(s) mediapackage.amazonaws.com
になります。
以上でIAMロールが準備できました。後ほどMediaPackageの設定でこのIAMロールのARNが必要となるので、控えておきます。(Role ARN)
認証コードの作成とSecrets Managerへの登録
認証コードを作成(決定)し、MediaPackageから参照するためSecrets Managerに保存します。
認証コードについて
認証コードについては、「長さが8~128文字であること」という制限があるとのことです。またUser Guideではversion 4 UUIDを使用することを推奨しているので、これにならいます。こちらのページを参考に、手元のMac環境でversion 4 UUIDを生成しました。
$ python Python 3.7.3 (default, Apr 23 2019, 11:32:00) [Clang 10.0.1 (clang-1001.0.46.4)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import uuid >>> str(uuid.uuid4()) '8e2f1c52-f77f-4147-940d-5574975a1f81'
この8e2f1c52-f77f-4147-940d-5574975a1f81
を本エントリでは認証コードとして扱います。
認証コードのSecrts Managerへの登録
作成した認証コードをMediaPackageから参照できるよう、Secrets Managerへ登録します。使用するMediaPackageと同じリージョンのSecrets Managerを使う点に注意しましょう。マネジメントコンソールのSecrets ManagerのページのSecretsから、[Store a new secret]ボタンで進みます。
secret typeはOther type of secrets
を選択、Secret key/value
の左側にKeyとしてMediaPackageCDNIdentifier
を、右側にキーの値として先ほど作成した認証コード8e2f1c52-f77f-4147-940d-5574975a1f81
を入力します。encryption keyはデフォルトキー(DefaultEncryptionKey
)としました。
Secret nameはMediaPackage/
プレフィックスを付けておきます。今回はMediaPackage/CDNAuthTest
としました
automatic rotationについてはDisableとしました。
内容を確認して、[Store]で認証コードをSecrets Managerに登録します。
以上で認証コードのSecrets Managerへの登録が完了です。後ほどMediaPackageの設定で作成したSecretのARNが必要になるので、控えておきます。
MediaPackageでCDN認証を有効にする
MediaPackage用のIAMロールの準備、そして認証コードの準備とSecrets Managerへの登録が完了したら、実際にMediaPackageのChannelを作成して、CDN認証を有効にしてみます。
現在のところCDN認証機能はMediaPackageのライブパッケージングのみで利用可能です。MediaPackageのマネジメントコンソール、Live > Channelsから[Create]でLive用のChannelを作成します。このMediaPackage Channel作成段階でCloudFrontディストリビューションもあわせて作成することもできますが、今回は後ほど別途作成することとします。
続いて作成したChannelにEndpointを作成します。Channelの詳細画面からEndpoints欄の[Add endpoints]ボタンで進みます。
Endpoint作成画面、今回はHLS用のEndpointとしました。Access control settingsの箇所でUse authorization
にチェックを入れます。Secrets role ARN
とCDN identifier secret
の項目が現れます。Secrets role ARN
には冒頭で作成したSecrets Managerへのアクセス権限を持つIAMロール(今回はMediaPackageCDNAuthRole)のARNを入力します。CDN identifier secret
の欄にはSecrets Managerで作成したSecret(今回はMediaPackage/CDNAuthTest-EDgwFi)のARNを入力します。
- Secrets role ARN
- arn:aws:iam::[AWSアカウントID]:role/MediaPackageCDNAuthRole
- CDN identifier secret
- arn:aws:secretsmanager:ap-northeast-1:[AWSアカウントID]:secret:MediaPackage/CDNAuthTest-EDgwFi
入力できたら[Save]でEndpointの追加を完了します。
CDN認証用のカスタムヘッダをつけてアクセスするようCloudFrontを設定する
続いてCDNとなるAmazon CloudFrontの設定です。今回はMediaPackageのマネジメントコンソールからではなく、CloudFrontのマネジメントコンソールからディストリビューションを作成してみました。
Origin Settingsの項目でOrigin Domain Nameについては、一覧から作成したMediaPackage ChannelのEndpointを選択します。今回、Origin Protocol PolicyについてはHTTPS Onlyにしました。そしてCDN認証用のカスタムヘッダの設定です。Origin Custom Headersの欄に、Header NameとしてX-MediaPackage-CDNIdentifier
を、Valueとして認証コード
(今回であれば8e2f1c52-f77f-4147-940d-5574975a1f81
を)入力します。
その他の項目を適切に設定し、CloudFrontディストリビューションを作成します。(今回は基本デフォルト設定ですが、Object CachingをUse Origin Cache Headersであることを確認し、またComment欄に確認用コメントを記載しました。)
CDN認証されていることを確認する
CloudFrontディストリビューション作成、利用可能になったら実際にCDN認証されていることを確認してみます。MediaPackageへはMediaLiveから映像を送信し、ライブ視聴が可能な状況としました。
まずは先ほど認証用の設定を行ったCloudFrontディストリビューション経由でアクセスしてみます。MediaPackageのEndpoint URLは以下となります。
- https://15bcxxxxxxxxxxxx.mediapackage.ap-northeast-1.amazonaws.com/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index.m3u8
ドメイン名をCloudFrontディストリビューションのものに置き換えて、以下でアクセスしてみます。
- https://d1dxxxxxxxxxx.cloudfront.net/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index.m3u8
視聴確認にはVideoJS HTTP Streamingを使用しました。Video URLにCloudFrontドメイン名のURLを入力し、MimeType:application/x-mpegURL
を確認して、[Load]ボタンを押します。問題なく再生できますね!
続いて、MediaPackageのエンドポイント(オリジン)に直接アクセスしてみましょう。以下のように403エラーとなってしまいました。オリジンへの直接アクセスが無効となっていることがわかります。
これらの内容を、curlコマンドを使って確認してみます。まずは認証設定を行ったCloudFrontからのアクセスです。m3u8ファイル、tsファイルとも、問題なくアクセスできていることが確認できます。
# トップレベルマニフェストファイル [shimizu.toshiya@classmethod] [~] $ curl https://d1dxxxxxxxxxx.cloudfront.net/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index.m3u8 #EXTM3U #EXT-X-VERSION:3 #EXT-X-INDEPENDENT-SEGMENTS #EXT-X-STREAM-INF:BANDWIDTH=5889549,AVERAGE-BANDWIDTH=3735564,RESOLUTION=1280x720,FRAME-RATE=29.970,CODECS="avc1.640029,mp4a.40.2" index_1.m3u8 [shimizu.toshiya@classmethod] [~] $ curl -I https://d1dxxxxxxxxxx.cloudfront.net/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index.m3u8 HTTP/2 200 content-type: application/x-mpegURL content-length: 197 date: Sun, 05 Jan 2020 07:32:16 GMT server: nginx/1.16.1 cache-control: max-age=2 access-control-allow-origin: * access-control-allow-credentials: true x-mediapackage-request-id: 1a7fdf73affd3507e97bf07a731bd9cb x-cache: Miss from cloudfront via: 1.1 9a4e1846c6e75906d748bf1a4ae650c7.cloudfront.net (CloudFront) x-amz-cf-pop: NRT20-C4 x-amz-cf-id: clTTa5a8UbQ7AeZRtmqELY3O8lwmxSLQAatjWwbk3r13vGs0G0qHAg== # ビットレートごとのマニフェストファイル(今回は1つのビットレートのみです) [shimizu.toshiya@classmethod] [~] $ curl https://d1dxxxxxxxxxx.cloudfront.net/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index_1.m3u8 #EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:7 #EXT-X-MEDIA-SEQUENCE:102 #EXTINF:6.006, index_1_102.ts?m=1578206347 #EXTINF:6.006, index_1_103.ts?m=1578206347 #EXTINF:6.006, index_1_104.ts?m=1578206347 #EXTINF:6.006, index_1_105.ts?m=1578206347 #EXTINF:6.006, index_1_106.ts?m=1578206347 #EXTINF:6.006, index_1_107.ts?m=1578206347 #EXTINF:6.006, index_1_108.ts?m=1578206347 #EXTINF:6.006, index_1_109.ts?m=1578206347 #EXTINF:6.006, index_1_110.ts?m=1578206347 #EXTINF:6.006, index_1_111.ts?m=1578206347 [shimizu.toshiya@classmethod] [~] $ curl -I https://d1dxxxxxxxxxx.cloudfront.net/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index_1.m3u8 HTTP/2 200 content-type: application/x-mpegURL content-length: 505 date: Sun, 05 Jan 2020 07:32:29 GMT server: nginx/1.16.1 cache-control: max-age=2 access-control-allow-origin: * access-control-allow-credentials: true x-mediapackage-request-id: 28c5727713bc3dc21c1a15487196eceb x-cache: Miss from cloudfront via: 1.1 01fbd7d01ff1478611d3936344040a80.cloudfront.net (CloudFront) x-amz-cf-pop: NRT20-C4 x-amz-cf-id: TcwEscWE8nudxhDd8wLcsvrBuoxT2pgpIYVD5LkpBAC_oBfdcS7bHA== # tsファイル [shimizu.toshiya@classmethod] [~] $ curl -I https://d1dxxxxxxxxxx.cloudfront.net/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index_1_111.ts HTTP/2 200 content-type: video/MP2T content-length: 2664524 date: Sun, 05 Jan 2020 07:32:57 GMT server: nginx/1.16.1 cache-control: max-age=21600 access-control-allow-origin: * access-control-allow-credentials: true x-mediapackage-request-id: a9c3998bebc6a268035cb0b34da0ef63 x-cache: Miss from cloudfront via: 1.1 ff8441cf5ba1180f46877d00029f6fec.cloudfront.net (CloudFront) x-amz-cf-pop: NRT20-C4 x-amz-cf-id: bGOv0aY4XdnAxSDAkBV2OFrdY76fO8Af0la0BR1Miz99clyw104nDA==
続いてMediaPackageのエンドポイントに直接アクセスしてみます。以下のように、403エラーでアクセスできないことがわかります。
# トップレベルマニフェストファイル [shimizu.toshiya@classmethod] [~] $ curl https://15bcxxxxxxxxxxxx.mediapackage.ap-northeast-1.amazonaws.com/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index.m3u8 <html> <head><title>403 Forbidden</title></head> <body bgcolor="white"> <center><h1>403 Forbidden</h1></center> </body> </html> [shimizu.toshiya@classmethod] [~] $ curl -I https://15bcxxxxxxxxxxxx.mediapackage.ap-northeast-1.amazonaws.com/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index.m3u8 HTTP/2 403 date: Sun, 05 Jan 2020 07:33:34 GMT content-type: text/html content-length: 127 server: nginx etag: "5df11fcd-7f" x-mediapackage-request-id: 39c3070eb09412e003f386bfe64f45ab # ビットレートごとのマニフェストファイル(今回は1つのビットレートのみです) [shimizu.toshiya@classmethod] [~] $ curl https://15bcxxxxxxxxxxxx.mediapackage.ap-northeast-1.amazonaws.com/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index_1.m3u8 <html> <head><title>403 Forbidden</title></head> <body bgcolor="white"> <center><h1>403 Forbidden</h1></center> </body> </html> [shimizu.toshiya@classmethod] [~] $ curl -I https://15bcxxxxxxxxxxxx.mediapackage.ap-northeast-1.amazonaws.com/ou t/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index_1.m3u8 HTTP/2 403 date: Sun, 05 Jan 2020 07:33:47 GMT content-type: text/html content-length: 127 server: nginx etag: "5df11fcd-7f" x-mediapackage-request-id: e8375b190767db29b128cdf2a15d8bf9 # tsファイル [shimizu.toshiya@classmethod] [~] $ curl -I https://15bcxxxxxxxxxxxx.mediapackage.ap-northeast-1.amazonaws.com/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index_1_111.ts HTTP/2 403 date: Sun, 05 Jan 2020 07:33:53 GMT content-type: text/html content-length: 127 server: nginx etag: "5df11fcd-7f" x-mediapackage-request-id: 9b497f87a32cb71b3f340cf01b36db23
続いてCloudFrontディストリビューションに設定したように、認証情報となるオリジンヘッダと認証コードを付与してのアクセスを確認してみましょう。curlコマンドにオプションで、ヘッダ名: X-MediaPackage-CDNIdentifier
、ヘッダの値: 8e2f1c52-f77f-4147-940d-5574975a1f81(認証コード)
を付与してアクセスしてみます。結果としては以下の通り、問題なくアクセスできることが確認できます。
# トップレベルマニフェストファイル [shimizu.toshiya@classmethod] [~] $ curl -H 'X-MediaPackage-CDNIdentifier:8e2f1c52-f77f-4147-940d-5574975a1f81' https://15bcxxxxxxxxxxxx.mediapackage.ap-northeast-1.amazonaws.com/out/v1/f030d80 624d54368b8de354f48d65dbb/index.m3u8 #EXTM3U #EXT-X-VERSION:3 #EXT-X-INDEPENDENT-SEGMENTS #EXT-X-STREAM-INF:BANDWIDTH=5889549,AVERAGE-BANDWIDTH=3735564,RESOLUTION=1280x720,FRAME-RATE=29.970,CODECS="avc1.640029,mp4a.40.2" index_1.m3u8 [shimizu.toshiya@classmethod] [~] $ curl -I -H 'X-MediaPackage-CDNIdentifier:8e2f1c52-f77f-4147-940d-5574975a1f81' https://15bcxxxxxxxxxxxx.mediapackage.ap-northeast-1.amazonaws.com/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index.m3u8 HTTP/2 200 date: Sun, 05 Jan 2020 07:35:18 GMT content-type: application/x-mpegURL content-length: 197 server: nginx/1.16.1 cache-control: max-age=2 access-control-allow-origin: * access-control-allow-credentials: true vary: Origin x-mediapackage-request-id: 9ce6de933e6737ca16306bc127c9e248 # ビットレートごとのマニフェストファイル(今回は1つのビットレートのみです) [shimizu.toshiya@classmethod] [~] $ curl -H 'X-MediaPackage-CDNIdentifier:8e2f1c52-f77f-4147-940d-5574975a1f81' https://15bcxxxxxxxxxxxx.mediapackage.ap-northeast-1.amazonaws.com/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index_1.m3u8 #EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:7 #EXT-X-MEDIA-SEQUENCE:133 #EXTINF:6.006, index_1_133.ts?m=1578206347 #EXTINF:6.006, index_1_134.ts?m=1578206347 #EXTINF:6.006, index_1_135.ts?m=1578206347 #EXTINF:6.006, index_1_136.ts?m=1578206347 #EXTINF:6.006, index_1_137.ts?m=1578206347 #EXTINF:6.006, index_1_138.ts?m=1578206347 #EXTINF:6.006, index_1_139.ts?m=1578206347 #EXTINF:6.006, index_1_140.ts?m=1578206347 #EXTINF:6.006, index_1_141.ts?m=1578206347 #EXTINF:6.006, index_1_142.ts?m=1578206347 [shimizu.toshiya@classmethod] [~] $ curl -I -H 'X-MediaPackage-CDNIdentifier:8e2f1c52-f77f-4147-940d-5574975a1f81' https://15bcxxxxxxxxxxxx.mediapackage.ap-northeast-1.amazonaws.com/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index_1.m3u8 HTTP/2 200 date: Sun, 05 Jan 2020 07:35:37 GMT content-type: application/x-mpegURL content-length: 505 server: nginx/1.16.1 cache-control: max-age=2 access-control-allow-origin: * access-control-allow-credentials: true vary: Origin x-mediapackage-request-id: 116dd66eb954c59db8073c650d687918 # tsファイル [shimizu.toshiya@classmethod] [~] $ curl -I -H 'X-MediaPackage-CDNIdentifier:8e2f1c52-f77f-4147-940d-5574975a1f81' https://15bcxxxxxxxxxxxx.mediapackage.ap-northeast-1.amazonaws.com/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index_1_142.ts HTTP/2 200 date: Sun, 05 Jan 2020 07:35:46 GMT content-type: video/MP2T content-length: 2688212 server: nginx/1.16.1 cache-control: max-age=21600 access-control-allow-origin: * access-control-allow-credentials: true vary: Origin x-mediapackage-request-id: 972f624d87acdd733c5400815314deeb
なお、当然ながらX-MediaPackage-CDNIdentifier
のヘッダを持っていても、認証コードが正しいものでなければアクセスはできません。
# トップレベルマニフェストファイル [shimizu.toshiya@classmethod] [~] $ curl -I -H 'X-MediaPackage-CDNIdentifier:happy-new-year' https://15bcxxxxxxxxxxxx.mediapackage.ap-northeast-1.amazonaws.com/out/v1/f030xxxxxxxxxxxxxxxxxxxxxxxxxxxx/index.m3u8 HTTP/2 403 date: Sun, 05 Jan 2020 07:43:28 GMT content-type: text/html content-length: 127 server: nginx etag: "5df11fcd-7f" x-mediapackage-request-id: 0f6f123ebeccf7d020ff34d6ed9c24f2
まとめ
AWS Elemental MediaPackageの認証機能によるオリジンエンドポイント保護について、実際に設定を行い確認してみました。これまでCloudFront側で署名付きCookieなどでアクセス可否を設定する場合などにおいて、オリジンとなるMediaPackageのアクセス保護は課題でした。IPアドレスでのアクセス許可設定は可能でしたが、CloudFrontの全IPを登録するなどはあまり現実的ではありません。仕方なく推測しにくいEndpoint URLのみで凌ぐ、ということもあったのではないでしょうか。今回の認証機能によるエンドポイント保護のアップデートで、よりセキュアに配信が行なえますね!非常にうれしいアップデートだと思います。2020年も引き続き、AWS Elemental MediaPackageをはじめとしたAWS Media Servicesの機能アップデートに注目していきたいと思います。